import os, sys
import subprocess
import threading


class MedusaCGI:
    def __init__(self, request, wsgi_handler, wsgi_application):
        self.request = request
        self.wsgi_handler = wsgi_handler
        self.wsgi_application = wsgi_application

    def do_cgi(self):
        # Populate as much of environ as we can.
        # This method spawns a new process and collects the
        # output and sends it back to the caller.
        self.payload = ""
        if hasattr(self.request, "pymq_payload"):
            self.payload = self.request.pymq_payload
        query = self.request.split_uri()[2]
        if not query:
            query = ""
        elif len(query) > 0:
            query = query[1:]


        # This complication is required since we want to COPY sys.path and not modify it.
        # Add the existing path and also the current module's directory and it's
        # parent directory to PYTHONPATH
        pyPath = []
        pyPath[:] = sys.path
        pyPath.append(os.path.dirname(__file__))
        pyPath.append(os.path.dirname(os.path.dirname(__file__)))

        environ = dict(os.environ.items())
        environ['REQUEST_METHOD']   = self.request.command
        environ['SERVER_PROTOCOL']  = 'HTTP/%s' % self.request.version
        environ['SERVER_SOFTWARE']  = "Medusa/pymq"
        environ['SERVER_NAME']      = "localhost" # TODO:
        environ['SERVER_PORT']      = "8080" # TODO:
        environ['QUERY_STRING']     = query
        environ['PATH_INFO']        = self.request.split_uri()[0]
        environ['PYTHONPATH']       = ";".join(pyPath)

        for header, value in self.request.get_headers().items():
            key = "HTTP_" + header.upper().replace("-", "_")
            environ[key] = value

        if self.request.command == "post":
            environ['CONTENT_LENGTH'] = str(len(self.payload))

        if environ.get('HTTPS','off') in ('on','1'):
            environ['wsgi.url_scheme'] = 'https'
        else:
            environ['wsgi.url_scheme'] = 'http'

        self.environ = environ
        threading.Thread(target=self).start()

    def __call__(self):
        child = None
        childReturn = 0
        out = err = ""

        # self.env = environ
        # import webapp.django_main as django_main
        # django_main.django_main(self)
        # self.run_with_cgi(self)

        try:
            # -u is for unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)
            child = subprocess.Popen([sys.executable, "-u", self.wsgi_handler, self.wsgi_application],
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     env=self.environ)
            out, err = child.communicate(input=self.payload)
            childReturn = child.returncode
        except Exception, e:
            print str(e)
            childReturn = 1

        if childReturn != 0:
            print "Client Stdout/Stderr: " + out + "/" + err
            self.request.push(err)
            self.request.reply_code = 500
            self.request.done_enqueue()
            return

        outParts = out.split("\r\n\r\n", 1)
        if len(outParts) != 2:
            self.request.reply_code = 500
            self.reply.done_enqueue()
            return

        responseHeaders = outParts[0].split("\r\n")
        if len(responseHeaders) < 1:
            self.request.reply_code = 500
            self.reply.done_enqueue()
            return

        try:
            returnCode = int(responseHeaders[0])
            responseHeaders = responseHeaders[1:]
            for header in responseHeaders:
                h = header.split(": ", 1)
                self.request[h[0]] = h[1]
        except Exception, e:
            print "Exception (%s) occurred while parsing result" % str(e)
            self.request.reply_code = 500
            self.request.done_enqueue()
            return

        self.request.push(outParts[1])
        self.request.response(returnCode)
        self.request.done_enqueue()

